|
Как известно, Visual Basic - не самое подходящее средство для
написания служб (Service) Windows NT/2000/XP. Проблема заключается в
том, что для написания службы требуется использование функции API
CreateThread, что не поддерживается
ни VB5, ни VB6. VB позволяет создавать многопоточные программы, но
не с помощью функции CreateThread.
VB5 использует общий объект Err для всех
потоков, созданных функцией API CreateThread. Это недопустимо, поскольку
изменение значений этого объекта может происходить из разных потоков
в непредсказуемой последовательности и даже одновременно на
многопроцессорных компьютерах. Напротив, VB6 использует для объекта
Err (и не только для него) локальную
память потока (TLS), но в момент создания потока функцией CreateThread TLS не инициализирована, и
поэтому после простой перекомпиляции в VB6 программа не работает
совсем (точнее, работает только при компиляции в p-code с общим
объектом Err).
Довольно сложный способ решения проблемы создания потоков в VB
предложил Мэтью Кэрланд (см. ссылки), но для создания службы можно
применить более простое решение. Программа будет работать и без TLS,
если в новом потоке совсем не использовать объект Err, а кроме этого использовать только
арифметические операторы и вызовы API, описанные в библиотеке типов.
Как известно, свойства объекта Err
обновляются в двух случаях: когда происходит Run-time ошибка (Err.Number), и после выполнения каждой функции
API (Err.LastDllError). Первого можно
избежать написанием безошибочного кода, второго - описанием функций
API с помощью библиотеки типов (описание функций API не должно
содержать атрибутов usesgetlasterror, поэтому библиотеки типов
из известной книги Брюса Мак-Кинни не годятся). Функциональная часть
службы должна работать в главном потоке, и на нее указанные
ограничения не распространяются. Этот подход работает как в VB6, так
и в VB5.
Разумеется, для создания своей службы вы можете использовать
бесплатный элемент управления NTSVC.OCX от Microsoft, и этот способ
достаточно прост и надежен, но имеет один недостаток: вы не можете
применять опцию "Unattended execution". Совместно с этой опцией
элементы управления OCX применяться не могут, а именно такой режим
работы для службы является предпочтительным. Кроме того, поскольку
этот элемент управления распространяется в виде исходного кода,
существует несколько откомпилированных версий этого компонента, не
вполне совместимых между собой.
Этот пример написан при помощи VB6 без использования каких-либо
внешних компонентов. Поскольку служба скомпилирована с опцией
"Unattended execution", она не имеет визуального интерфейса. Для
просмотра сообщений, записываемых службой в Application Log,
используйте Event Viewer.
Функциональная часть службы (отсутствующая в данном примере)
должна управляться событиями, поступающими от Диспетчера Служб. Все
события должны обрабатываться в течение нескольких секунд, в
противном случае служба не будет иметь возможности обрабатывать
запросы Диспетчера Служб.
См. также:
Microsoft Knowledge Base Q137890, Q170883, Q175948,
An OLE Control for Creating Win32 Services in Visual
Basic,
Manipulate Windows NT Services by Writing a Service
Control Program,
Creating an Agent NT Service with VB,
How-To Run Your Application as a Service,
How-To Run Your Application as a Service - Part
II,
Статью Мэтью Кэрланда "Create Worker Threads in DLLs" в журнале "Visual Basic
Programmer's Journal" за июнь 1999 года. |